﻿#region << 文件说明 >>

/*----------------------------------------------------------------
 * 命名空间：Vampirewal.Core.RuleEngine.Interfaces
 * 唯一标识：76e16b3d-9293-4c24-b3a2-d84d605dd632
 * 文件名：IVampirewalRuleBuilder
 *
 * 创建者：杨程
 * 电子邮箱：235160615@qq.com
 * 创建时间：2023/10/12 13:44:30
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 文件说明 >>

namespace Vampirewal.Core.RuleEngine;

/// <summary>
/// 规则构建器
/// </summary>
/// <typeparam name="TData"></typeparam>
public interface IVampirewalRuleBuilder<TData> where TData : class, new()
{
    /// <summary>
    /// 开始步骤
    /// </summary>
    /// <typeparam name="ISetp"></typeparam>
    /// <returns></returns>
    IVampirewalRuleBuilder<TData> StartWith<ISetp>() where ISetp : IVampirewalRuleSetp<TData>;

    /// <summary>
    /// 单独IF步骤
    /// </summary>
    /// <typeparam name="ISetp"></typeparam>
    /// <param name="Condition"></param>
    /// <returns></returns>
    IVampirewalRuleBuilder<TData> IF<ISetp>(Expression<Func<TData, bool>> Condition) where ISetp : IVampirewalRuleSetp<TData>;

    /// <summary>
    /// IF和ELSE步骤
    /// </summary>
    /// <typeparam name="IFSetp"></typeparam>
    /// <typeparam name="ElseSetp"></typeparam>
    /// <param name="Condition">返回true执行If，返回false执行else</param>
    /// <returns></returns>
    IVampirewalRuleBuilder<TData> IfElse<IFSetp, ElseSetp>(Expression<Func<TData, bool>> Condition) where IFSetp : IVampirewalRuleSetp<TData> where ElseSetp : IVampirewalRuleSetp<TData>;


    
}

internal class VampirewalRuleBuilder<T> : IVampirewalRuleBuilder<T> where T : class, new()
{
    public T? Data { get; set; }

    internal IServiceProvider Service { get; set; }

    internal VampirewalRuleEngineOption Option { get; set; }

    internal List<IVampirewalRuleSetp<T>> Setps { get; set; }

    public VampirewalRuleBuilder(T? data)
    {
        Setps = new List<IVampirewalRuleSetp<T>>();
        Data = data;
        Context = new VampirewalRuleSetpContext<T>()
        {
            Data = data,
            Service=this.Service,
            Builder=this
        };
    }

    public VampirewalRuleSetpContext<T> Context { get; set; }

    public IVampirewalRuleBuilder<T> StartWith<ISetp>() where ISetp : IVampirewalRuleSetp<T>
    {
        if (Context.HasStart)
        {
            throw new Exception("不能重复执行StartWith！");
        }

        var setp = Activator.CreateInstance(typeof(ISetp)) as IVampirewalRuleSetp<T>;

        setp.Run(Context);

        Context.HasStart = true;
        return this;
    }

    public IVampirewalRuleBuilder<T> IfElse<IFSetp, ElseSetp>(Expression<Func<T, bool>> Condition) where IFSetp : IVampirewalRuleSetp<T> where ElseSetp : IVampirewalRuleSetp<T>
    {
        if (!Context.HasStart)
        {
            throw new Exception("不能没有StartWith！");
        }

        if (Context.HasEnd)
        {
            throw new Exception("该规则引擎流转已经结束！");
        }

        var result = Condition.Compile().Invoke(Data);
        if (result)
        {
            var setp = Activator.CreateInstance(typeof(IFSetp)) as IVampirewalRuleSetp<T>;
            setp.Run(Context);
        }
        else
        {
            var setp2 = Activator.CreateInstance(typeof(ElseSetp)) as IVampirewalRuleSetp<T>;
            setp2.Run(Context);
        }

        return this;
    }

    public IVampirewalRuleBuilder<T> IF<IFSetp>(Expression<Func<T, bool>> Condition) where IFSetp : IVampirewalRuleSetp<T>
    {
        if (!Context.HasStart)
        {
            throw new Exception("不能没有StartWith！");
        }

        if (Context.HasEnd)
        {
            throw new Exception("该规则引擎流转已经结束！");
        }

        var result = Condition.Compile().Invoke(Data);
        if (result)
        {
            var setp = Activator.CreateInstance(typeof(IFSetp)) as IVampirewalRuleSetp<T>;
            setp.Run(Context);
        }

        return this;
    }

    public void End()
    {
        if (Context.HasEnd)
        {
            throw new Exception("该规则引擎流转已经结束！");
        }

        Context.HasEnd = true;
    }
}